package smarthome

import (
	"fmt"
	"time"
)

// Command 命令接口
type Command interface {
	Execute()
	Undo()
	GetName() string
}

// 具体命令
// BaseDeviceCommand 基础设备命令
type BaseDeviceCommand struct {
	device   Device
	preState string
}

func (r *BaseDeviceCommand) saveState() {
	r.preState = r.device.GetStatus()
}

// LightOnCommand 开灯命令
type LightOnCommand struct {
	*BaseDeviceCommand
}

func NewLightOnCommand(light *Light) *LightOnCommand {
	cmd := &LightOnCommand{
		BaseDeviceCommand: &BaseDeviceCommand{
			device: light,
		},
	}
	cmd.saveState()
	return cmd
}

func (r *LightOnCommand) Execute() {
	r.device.On()
}

func (r *LightOnCommand) Undo() {
	if r.preState == "关" {
		r.device.Off()
	} else {
		// 恢复之前的亮度等状态
		fmt.Printf("恢复%s灯到之前状态: %s\n", r.device.GetName(), r.preState)
	}
}

func (r *LightOnCommand) GetName() string {
	return r.device.GetName() + "开灯"
}

// 关灯命令
type LightOffCommand struct {
	BaseDeviceCommand
}

func NewLightOffCommand(light *Light) *LightOffCommand {
	cmd := &LightOffCommand{
		BaseDeviceCommand: BaseDeviceCommand{device: light},
	}
	cmd.saveState()
	return cmd
}

func (c *LightOffCommand) Execute() {
	c.device.Off()
}

func (c *LightOffCommand) Undo() {
	if c.preState != "关" {
		c.device.On()
	}
}

func (c *LightOffCommand) GetName() string {
	return "关闭" + c.device.GetName()
}

// 设置灯光亮度命令
type SetBrightnessCommand struct {
	BaseDeviceCommand
	level     int
	prevLevel int
}

func NewSetBrightnessCommand(light *Light, level int) *SetBrightnessCommand {
	cmd := &SetBrightnessCommand{
		BaseDeviceCommand: BaseDeviceCommand{device: light},
		level:             level,
		prevLevel:         light.Bright,
	}
	return cmd
}

func (c *SetBrightnessCommand) Execute() {
	c.device.(*Light).SetBright(c.level)
}

func (c *SetBrightnessCommand) Undo() {
	c.device.(*Light).SetBright(c.prevLevel)
}

func (c *SetBrightnessCommand) GetName() string {
	return fmt.Sprintf("设置%s灯亮度为%d%%", c.device.GetName(), c.level)
}

// 空调命令
type ACOnCommand struct {
	BaseDeviceCommand
}

func NewACOnCommand(ac *AirConditioner) *ACOnCommand {
	cmd := &ACOnCommand{
		BaseDeviceCommand: BaseDeviceCommand{device: ac},
	}
	cmd.saveState()
	return cmd
}

func (c *ACOnCommand) Execute() {
	c.device.On()
}

func (c *ACOnCommand) Undo() {
	if c.preState == "关" {
		c.device.Off()
	}
}

func (c *ACOnCommand) GetName() string {
	return "打开" + c.device.GetName()
}

// 设置空调温度命令
type SetACTemperatureCommand struct {
	BaseDeviceCommand
	temp     int
	prevTemp int
}

func NewSetACTemperatureCommand(ac *AirConditioner, temp int) *SetACTemperatureCommand {
	cmd := &SetACTemperatureCommand{
		BaseDeviceCommand: BaseDeviceCommand{device: ac},
		temp:              temp,
		prevTemp:          ac.Temperature,
	}
	return cmd
}

func (c *SetACTemperatureCommand) Execute() {
	c.device.(*AirConditioner).SetTemperature(c.temp)
}

func (c *SetACTemperatureCommand) Undo() {
	c.device.(*AirConditioner).SetTemperature(c.prevTemp)
}

func (c *SetACTemperatureCommand) GetName() string {
	return fmt.Sprintf("设置%s温度为%d℃", c.device.GetName(), c.temp)
}

// ========= 宏命令 =========
type MacroCommand struct {
	name     string
	commands []Command
}

func NewMacroCommand(name string, commands ...Command) *MacroCommand {
	return &MacroCommand{
		name:     name,
		commands: commands,
	}
}

func (m *MacroCommand) Execute() {
	fmt.Printf("开始执行宏命令: %s\n", m.name)
	for _, cmd := range m.commands {
		cmd.Execute()
		time.Sleep(200 * time.Millisecond) // 模拟执行间隔
	}
	fmt.Println("宏命令执行完成")
}

func (m *MacroCommand) Undo() {
	fmt.Printf("撤销宏命令: %s\n", m.name)
	// 按相反顺序撤销
	for i := len(m.commands) - 1; i >= 0; i-- {
		m.commands[i].Undo()
		time.Sleep(200 * time.Millisecond)
	}
}

func (m *MacroCommand) GetName() string {
	return m.name
}
